﻿using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Text;
using System.Threading.Tasks;

using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.ObjectMapping;
using Volo.Abp.Uow;
using Volo.Abp.Validation;

using Wms.Manager.Common;
using Wms.Manager.Common.Dtos;
using Wms.Manager.Permissions;
using Wms.Manager.Wms.InventoryManagements.Dtos;

namespace Wms.Manager.Wms.InventoryManagements
{
    [Authorize(WmsPermissions.Default)]
    public class InventoryManagementAppService : ManagerAppService, IInventoryManagementAppService
    {
        private readonly IRepository<InventoryManagement, Guid> _inventoryRepository;

        private readonly IImportExportService<InventoryManagementImportExportDto> _importExportService;
        public InventoryManagementAppService(IRepository<InventoryManagement, Guid> inventoryRepository, IImportExportService<InventoryManagementImportExportDto> importExportService)
        {
            _inventoryRepository = inventoryRepository;
            _importExportService = importExportService;
        }

        #region CURD


        [Authorize(WmsPermissions.Default)]
        public async Task<PagedResultDto<InventoryManagementDto>> GetListAsync(InventoryManagementFilterDto input)
        {
            var query = await _inventoryRepository.GetQueryableAsync();

            // 使用WhereIf链式构建查询条件
            query = query
                .WhereIf(!string.IsNullOrEmpty(input.InventoryName), x => x.InventoryName.Contains(input.InventoryName))
                .WhereIf(!string.IsNullOrEmpty(input.BatchNumber), x => x.BatchNumber.Contains(input.BatchNumber))
                .WhereIf(!string.IsNullOrEmpty(input.LocationName), x => x.LocationName.Contains(input.LocationName))
                .WhereIf(input.MinQuantity.HasValue, x => x.CurrentQuantity >= input.MinQuantity)
                .WhereIf(input.MaxQuantity.HasValue, x => x.CurrentQuantity <= input.MaxQuantity)
                .WhereIf(input.CreationTimeStart.HasValue, x => x.CreationTime >= input.CreationTimeStart)
                .WhereIf(input.CreationTimeEnd.HasValue, x => x.CreationTime <= input.CreationTimeEnd);

            // 执行分页查询
            var totalCount = await AsyncExecuter.CountAsync(query);
            var items = await AsyncExecuter.ToListAsync(query
                .OrderBy(input.Sorting ?? nameof(InventoryManagement.CreationTime) + " DESC")
                .PageBy(input));

            return new PagedResultDto<InventoryManagementDto>(
                totalCount,
                ObjectMapper.Map<List<InventoryManagement>, List<InventoryManagementDto>>(items)
            );
        }

        [Authorize(WmsPermissions.Default)]
        public async Task<InventoryManagementDto> GetAsync(Guid id)
        {
            var entity = await _inventoryRepository.GetAsync(id);
            return ObjectMapper.Map<InventoryManagement, InventoryManagementDto>(entity);
        }

        [Authorize(WmsPermissions.Create)]
        public async Task<InventoryManagementDto> CreateAsync(CreateInventoryManagementDto input)
        {
            // 检查批次号是否已存在
            var exists = await _inventoryRepository.AnyAsync(x => x.BatchNumber == input.BatchNumber);
            if (exists)
            {
                throw new UserFriendlyException("批次号已存在");
            }

            var entity = ObjectMapper.Map<CreateInventoryManagementDto, InventoryManagement>(input);

            // 设置创建人信息（如果需要）
            if (CurrentUser.IsAuthenticated)
            {
                entity.CreatorId = CurrentUser.Id;
            }

            var createdEntity = await _inventoryRepository.InsertAsync(entity, autoSave: true);
            return ObjectMapper.Map<InventoryManagement, InventoryManagementDto>(createdEntity);
        }

        [Authorize(WmsPermissions.Update)]
        public async Task<InventoryManagementDto> UpdateAsync(Guid id, UpdateInventoryManagementDto input)
        {
            var entity = await _inventoryRepository.GetAsync(id);

            // 检查批次号是否已被其他记录使用
            if (entity.BatchNumber != input.BatchNumber)
            {
                var exists = await _inventoryRepository.AnyAsync(x =>
                    x.BatchNumber == input.BatchNumber && x.Id != id);
                if (exists)
                {
                    throw new UserFriendlyException("批次号已被其他记录使用");
                }
            }

            // 使用对象映射更新实体属性
            ObjectMapper.Map(input, entity);

            // 设置修改人信息（如果需要）
            if (CurrentUser.IsAuthenticated)
            {
                entity.LastModifierId = CurrentUser.Id;
            }

            var updatedEntity = await _inventoryRepository.UpdateAsync(entity, autoSave: true);
            return ObjectMapper.Map<InventoryManagement, InventoryManagementDto>(updatedEntity);
        }

        [Authorize(WmsPermissions.Delete)]
        public async Task DeleteAsync(Guid id)
        {
            // 检查库存是否允许删除（例如数量是否为0）
            var entity = await _inventoryRepository.GetAsync(id);
            if (entity.CurrentQuantity > 0)
            {
                throw new UserFriendlyException("库存数量不为0，无法删除");
            }

            await _inventoryRepository.DeleteAsync(id);
        }

        [Authorize(WmsPermissions.Delete)]
        public async Task DeleteAsync(IEnumerable<Guid> ids)
        {
            if (ids == null || !ids.Any())
            {
                return; // 空集合直接返回
            }

            // 1. 检查所有ID对应的库存记录是否存在
            var entities = await _inventoryRepository.GetListAsync(x => ids.Contains(x.Id));

            // 2. 验证是否所有记录都允许删除（例如数量是否为0）
            var invalidItems = entities.Where(x => x.CurrentQuantity > 0).ToList();
            if (invalidItems.Any())
            {
                throw new UserFriendlyException($"以下库存ID数量不为0，无法删除：{string.Join(",", invalidItems.Select(x => x.Id))}");
            }

            // 3. 执行批量删除
            await _inventoryRepository.DeleteManyAsync(ids);
        }

        [Authorize(WmsPermissions.Create)]
        public async Task InsertManyAsync(List<InventoryManagementImportExportDto> data)
        {
            var entities = ObjectMapper.Map<List<InventoryManagementImportExportDto>, List<InventoryManagement>>(data);

            await _inventoryRepository.InsertManyAsync(entities);
        }
        #endregion

        #region 导入导出

        /// <summary>
        /// 导出
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        [Authorize(WmsPermissions.Export)]
        [ApiExplorerSettings(IgnoreApi = true)]
        public async Task<byte[]> ExportInventoryAsync(List<Guid> ids = null)
        {
            var queryable = await _inventoryRepository.GetQueryableAsync();

            if (ids != null && ids.Any())
            {
                queryable = queryable.Where(x => ids.Contains(x.Id));
            }

            var entities = queryable.ToList();
            var dtos = ObjectMapper.Map<List<InventoryManagement>, List<InventoryManagementImportExportDto>>(entities);

            return await _importExportService.ExportToExcelAsync(dtos, "库存管理数据");
        }

      
        [Authorize(WmsPermissions.Export)]
        [ApiExplorerSettings(IgnoreApi = true)]
        public async Task<byte[]> ExportTemplateAsync()
        {
            // 创建一个空的模板，包含示例数据
            var templateData = new List<InventoryManagementImportExportDto>
            {
                new InventoryManagementImportExportDto
                {
                    InventoryName = "示例商品A",
                    CurrentQuantity = 100,
                    BatchNumber = "BATCH001",
                    LocationName = "A01-01-01",
                    Remark = "这是示例数据，请删除后填入真实数据"
                }
            };

            return await _importExportService.ExportToExcelAsync(templateData, "库存管理导入模板");
        }


        [Authorize(WmsPermissions.Import)]
        [ApiExplorerSettings(IgnoreApi = true)]
        [DisableValidation]
        public async Task<ImportResult<InventoryManagementImportExportDto>> ImportInventoryAsync(Stream fileStream)
        {
            var result = await _importExportService.ImportFromExcelWithValidationAsync(fileStream);

            // 可以在这里添加业务层面的验证
            await ValidateBusinessRulesAsync(result);

            return result;
        }


        private async Task ValidateBusinessRulesAsync(ImportResult<InventoryManagementImportExportDto> result)
        {
            // 示例：检查批次号是否重复
            var batchNumbers = result.SuccessData.Select(x => x.BatchNumber).ToList();
            var duplicateBatches = batchNumbers.GroupBy(x => x)
                .Where(g => g.Count() > 1)
                .Select(g => g.Key)
                .ToList();

            if (duplicateBatches.Any())
            {
                for (int i = 0; i < result.SuccessData.Count; i++)
                {
                    if (duplicateBatches.Contains(result.SuccessData[i].BatchNumber))
                    {
                        result.Errors.Add(new ImportError
                        {
                            Row = i + 2, // Excel行号
                            Column = "批次号",
                            Message = "批次号在导入数据中重复",
                            Value = result.SuccessData[i].BatchNumber
                        });
                    }
                }

                // 移除有错误的数据
                result.SuccessData.RemoveAll(x => duplicateBatches.Contains(x.BatchNumber));
            }

            // 示例：检查数据库中是否已存在相同批次号
            var existingBatchNumbers = await _inventoryRepository.GetListAsync(x => batchNumbers.Contains(x.BatchNumber));
            var existingBatches = existingBatchNumbers.Select(x => x.BatchNumber).ToList();

            if (existingBatches.Any())
            {
                for (int i = 0; i < result.SuccessData.Count; i++)
                {
                    if (existingBatches.Contains(result.SuccessData[i].BatchNumber))
                    {
                        result.Errors.Add(new ImportError
                        {
                            Row = i + 2,
                            Column = "批次号",
                            Message = "批次号在数据库中已存在",
                            Value = result.SuccessData[i].BatchNumber
                        });
                    }
                }

                result.SuccessData.RemoveAll(x => existingBatches.Contains(x.BatchNumber));
            }
        }
        #endregion
    }
}
